﻿/**
* @description  Tweens both x and y position of an object, and allows for basic motion blur.
*/
package com.foed.animation {

	import flash.display.DisplayObject;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	
	import com.foed.events.TweenEvent;
	
	public class Mover extends Animator {
	
		private var _tween:TweenRunner;
		private var _clip:DisplayObject;
		private var _useBlur:Boolean;
		private var _blurAmount:Number;
		private var _blurQuality:int;
		private var _blurFilter:BlurFilter;
		private var _startValue:Object;
		private var _destValue:Object;
		private var _time:Number;
		private var _easeFunction:Function;
		private var _lastPosition:Point;
	
		/**
		* @description  Constructor.
		*
		* @param  pClip  The object on which the tween will perform.
		* @param  pStartValue  The value of the x and y properties at the start of the tween.
		* @param  pDestValue  The value of the x and y properties at the end of the tween.
		* @param  pTime  The number of milliseconds the tween should run.
		* @param  pEaseFunction  The function to use to calculate values during the tween.
		* @param  pBlur  Whether the mover should apply faux motion blur.
		* @param  pBlurFactor  The amount that the mover will blur the object in motion.
		* @param  pBlurQuality  The number of passes the blur filter will use.
		*/
		public function Mover(
			pClip:DisplayObject,
			pStartValue:Point,
			pDestValue:Point,
			pTime:Number,
			pEaseFunction:Function=null,
			pUseBlur:Boolean=false,
			pBlurAmount:Number=1,
			pBlurQuality:int=1
		) {
			_clip = pClip;
			_startValue = {x:pStartValue.x, y:pStartValue.y};
			_destValue = {x:pDestValue.x, y:pDestValue.y};
			_time = pTime;
			_easeFunction = pEaseFunction;
			_useBlur = pUseBlur;
			_blurAmount = pBlurAmount;
			_blurQuality = pBlurQuality;
		}
	
		/**
		* @description  Called once the TweenRunner completes the tween.
		*
		* @param  pEvent  Event fired by TweenRunner.
		*/
		private function onEndTween(pEvent:TweenEvent):void {
			halt();
			dispatchEvent(new TweenEvent(TweenEvent.END, this));
		}
	
		/**
		* @description  Event handler for TweenRunner's animation interval.
		*
		* @param  pEvent  Event fired by TweenRunner.
		*/
		private function onChangeTween(pEvent:TweenEvent):void {
			var pChangedValues:Object = _tween.value;
			_clip.x = pChangedValues.x;
			_clip.y = pChangedValues.y;
			if (_useBlur) {
				var pFactor:Number = _blurAmount/10;
				_blurFilter.blurX = Math.abs((pChangedValues.x - _lastPosition.x)*pFactor);
				_blurFilter.blurY = Math.abs((pChangedValues.y - _lastPosition.y)*pFactor);
				var pFilters:Array = _clip.filters.slice(0, -1);
				_clip.filters = pFilters.concat(_blurFilter);
				_lastPosition = new Point(pChangedValues.x, pChangedValues.y);
			}
			dispatchEvent(new TweenEvent(TweenEvent.CHANGE, this));
		}
		
		/**
		* @description  Stops the animation.
		*/
		override public function halt():void {
			if (_useBlur) {
				_clip.filters = _clip.filters.slice(0, -1);
			}
			_tween.removeEventListener(TweenEvent.CHANGE, onChangeTween);
			_tween.removeEventListener(TweenEvent.END, onEndTween);
			_tween.halt();
		}
	
		/**
		* @description  Starts the animation.
		*/
		override public function start():void {
			_tween = new TweenRunner(_startValue, _destValue, _time, _easeFunction);
			_tween.addEventListener(TweenEvent.CHANGE, onChangeTween);
			_tween.addEventListener(TweenEvent.END, onEndTween);
			if (_useBlur) {
				_lastPosition = new Point(_clip.x, _clip.y);
				var pFilters:Array = _clip.filters || [];
				_blurFilter = new BlurFilter(0, 0, _blurQuality);
				pFilters.push(_blurFilter);
				_clip.filters = pFilters;
			}
			_tween.start();
			dispatchEvent(new TweenEvent(TweenEvent.START, this));
		}
	
	}
	
}